package com.tq.http;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import com.tq.util.ImgUtil;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;

import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;

public class ImageLoader {

	private ImgUtil imgUtil;
	private static final int CACHE_CAPACITY = 100;

	private static final ConcurrentHashMap<String, SoftReference<Bitmap>> softCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>(
			CACHE_CAPACITY / 2);

	private static final LinkedHashMap<String, Bitmap> hardCache = new LinkedHashMap<String, Bitmap>(
			CACHE_CAPACITY / 2, 0.75f, true) {

		protected boolean removeEldestEntry(
				java.util.Map.Entry<String, Bitmap> eldest) {

			if (size() > CACHE_CAPACITY) {

				softCache.put(eldest.getKey(),
						new SoftReference<Bitmap>(eldest.getValue()));
				return true;
			}

			return false;

		};

	};
	
	
	
	public ImageLoader() {
		super();
		imgUtil=new ImgUtil();
	}

	//从缓存中的得到
	private Bitmap getBitmapFromCache(String url) {

		synchronized (hardCache) {

			Bitmap bitmap = hardCache.get(url);
			if (null != bitmap) {
				// move the element to first postion . so that it is remove
				// last;
				hardCache.remove(url);
				hardCache.put(url, bitmap);
				
				return bitmap;
			}
		}

		SoftReference<Bitmap> softReference = softCache.get(url);

		if (null != softReference) {
			Bitmap bitmap = softReference.get();
			if (null != bitmap)
				return bitmap;
		} else {
			softCache.remove(url);
		}
		
		return null;
	}
	
	public void download(String url, ImageView imgView) {

		// 缓存存在
		Bitmap bitmap = getBitmapFromCache(url);
		if (bitmap != null) {
			imgView.setImageBitmap(bitmap);
			canclePotentialDownload(url, imgView);
			
			return;
		}

		// 缓存不存在
		if (canclePotentialDownload(url, imgView)) {

			bitmap = imgUtil.getBitmapFromSd(url);
			if (bitmap != null) {
				imgView.setImageBitmap(bitmap);
				
				return;
			} else {
				ImageDownloadTask task = new ImageDownloadTask(imgView);
				ImageloaderDrawable drawable = new ImageloaderDrawable(task);
				imgView.setImageDrawable(drawable);

				task.execute(url);
				
			}

		}
	}
	
	private boolean canclePotentialDownload(String url, ImageView imageView) {

		ImageDownloadTask task = getImageDownloadTask(imageView);

		if (null != task) {
			String downurl = task.url;

			if (null == downurl || !downurl.equals(url))
				task.cancel(true);
			else {
				return false;
			}
		}
		return true;
	}
	
	private ImageDownloadTask getImageDownloadTask(ImageView imageView) {

		if (null != imageView) {
			Drawable drawable = imageView.getDrawable();

			if (drawable instanceof ImageloaderDrawable)
				return ((ImageloaderDrawable) drawable).getImageDownloadTask();
		}

		return null;
	}

	class ImageDownloadTask extends AsyncTask<String, Void, Bitmap> {

		private String url;
		private WeakReference<ImageView> imgViReference;

		public ImageDownloadTask(ImageView imageView) {

			imgViReference = new WeakReference<ImageView>(imageView);

		}

		@Override
		protected Bitmap doInBackground(String... params) {

			url = params[0];
			return downloadBitmap(url);
		}

		@Override
		protected void onPostExecute(Bitmap result) {

			if (isCancelled())
				result = null;

			// 把bitmap 放到缓存中
			addBitmapToCache(url, result);

			imgUtil.writeBitmap2Sd(url, result);
			if (null != result) {
				ImageView imageView = imgViReference.get();

				if (null != imageView) {
					ImageDownloadTask task = getImageDownloadTask(imageView);
					if (this == task)
						imageView.setImageBitmap(result);
				}

			}

		}

	}
	
	private void addBitmapToCache(String url, Bitmap bitmap) {

		if (null != bitmap) {
			synchronized (hardCache) {
				hardCache.put(url, bitmap);
			}
		}

	}

	class ImageloaderDrawable extends ColorDrawable {

		private final WeakReference<ImageDownloadTask> taskReference;

		public ImageloaderDrawable(ImageDownloadTask task) {
			super(Color.BLACK);
			taskReference = new WeakReference<ImageLoader.ImageDownloadTask>(
					task);
		}

		public ImageDownloadTask getImageDownloadTask() {
			return taskReference.get();
		}

	}
	
	private Bitmap downloadBitmap(String url) {
		// AndroidHttpClient is not allowed to be used from the main thread
		// final HttpClient client = (mode == Mode.NO_ASYNC_TASK) ? new
		// DefaultHttpClient() :
		// AndroidHttpClient.newInstance("Android");
		final HttpClient client = new DefaultHttpClient();
		final HttpGet getRequest = new HttpGet(url);

		try {
			HttpResponse response = client.execute(getRequest);
			
			final int statusCode = response.getStatusLine().getStatusCode();

			if (statusCode != HttpStatus.SC_OK) {

				return null;
			}

			final HttpEntity entity = response.getEntity();
			if (entity != null) {
				InputStream inputStream = null;
				try {
					inputStream = entity.getContent();
					return BitmapFactory.decodeStream(inputStream);
					// Bug on slow connections, fixed in future release.
					// return BitmapFactory.decodeStream(new
					// FlushedInputStream(inputStream));
				} finally {
					if (inputStream != null) {
						inputStream.close();
					}
					entity.consumeContent();
				}
			}
		} catch (IOException e) {
			getRequest.abort();
			
		} catch (IllegalStateException e) {
			getRequest.abort();
			
		} catch (Exception e) {
			getRequest.abort();
			
		} finally {
					
		}
		return null;
	}

}
